package cn.com.connext.scrm.task;

import cn.com.connext.scrm.config.Constants;
import cn.com.connext.scrm.domain.master.*;
import cn.com.connext.scrm.service.ErpLogisticsService;
import cn.com.connext.scrm.service.MemberService;
import cn.com.connext.scrm.service.PrizeGoodService;
import cn.com.connext.scrm.service.dto.JsonResult;
import cn.com.connext.scrm.service.mapper.OrderService;
import cn.com.connext.scrm.service.mapper.ProductService;
import cn.com.connext.scrm.utils.wdtutils.WdtClient;
import cn.com.connext.scrm.web.rest.WxOrderResource;
import cn.com.connext.scrm.web.rest.enums.LogisticsPushStateEnum;
import cn.com.connext.scrm.web.rest.enums.OrderTypeEnum;
import cn.com.connext.scrm.web.rest.req.OrderQueryReq;
import cn.com.connext.scrm.web.rest.resp.OrderResp;
import cn.com.connext.scrm.web.rest.vm.TradeVM;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.connext.common.util.DateUtil;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;

import java.io.IOException;
import java.util.*;

/**
 * @Description: 订单推送定时任务 （物流单号回写）
 * @author: ZHaoYul
 * @date: 2021/4/20 15:54
 */

@Component
@RestController
public class OrderPushLogisticsWriteBackTask {

    private final Logger log = LoggerFactory.getLogger(OrderPushLogisticsWriteBackTask.class);
    @Autowired
    private WxOrderResource wxOrderResource;
    @Autowired
    private MemberService memberService;
    @Autowired
    private OrderService orderService;
    @Autowired
    private ErpLogisticsService erpLogisticsService;
    @Autowired
    private ProductService productService;
    @Autowired
    private PrizeGoodService prizeGoodService;

    /**
     *
     */
    //每十分钟执行一次
    @Scheduled(cron = "0 0/30 * * * ?")
    @PostMapping("/orderPushLogisticsTask")
    public void orderPushLogisticsTask(){
        this.queryList(20,1);
    }
    public void queryList(int pageSize, int currentPage){
        List<Map<String, Object>> trade_list = new ArrayList<Map<String, Object>>();
        //分页查询订单状态为兑换成功 且erp编码为空的数据
        List<OrderResp> orderList = this.getOrderList(pageSize, currentPage);
        List<OrderRecord> list = new ArrayList<>();
        if (CollectionUtils.isEmpty(orderList)) {
            //未查询到符合的订单信息
            log.info("未查询到符合的订单信息");
            return;
        }

        for (OrderResp orderResp : orderList) {
            String addressDetails = "";
            if (StringUtils.isBlank(orderResp.getUserId())) {
                log.info("用户信息为空，跳出");
                continue;
            }

            //物流地址
            if (StringUtils.isNotBlank(orderResp.getLogisticsAddress())) {
                String logisticsAddress = orderResp.getLogisticsAddress();
                addressDetails = logisticsAddress.replace("/", " ");
            } else {
                log.info("地址信息未维护，跳出");
                continue;
            }

            Map<String,String> map = new HashMap<>();
            //订单类型为实物 且 goodType 为空 查询product
            if (OrderTypeEnum.ORDER_TYPE_20.getCode() == orderResp.getOrderType() && StringUtils.isNotBlank(orderResp.getGoodType())) {
                //实物订单 根据 productID 查 奖品表
                PrizeGood byId = prizeGoodService.findById(Integer.valueOf(orderResp.getProductId()));
                map.put("goods_id",String.valueOf(byId.getId()));
                map.put("goods_Name",byId.getGoodName());
                map.put("goods_Code",byId.getGoodCode());
            } else {
                Product product =  productService.getProductDetails(orderResp.getProductId());
                map.put("goods_id",product.getId());
                map.put("goods_Name",product.getName());
                map.put("goods_Code",product.getGoodCode());
            }

            //查询会员信息
            Member memberDetails = orderService.getMemberDetails(orderResp.getUserId());
            memberDetails.setAddress(addressDetails);
            //调用数据组装
            this.assembleOrderData(orderResp,trade_list,map,memberDetails);
            OrderRecord orderRecord = new OrderRecord();
            orderRecord.setId(orderResp.getId());
            orderRecord.setOrderCode(orderResp.getOrderCode());
            list.add(orderRecord);
        }
        String data = JSON.toJSONString(trade_list);
        //调用erp
        String send = this.send(data);
        JSONObject jsonObject = JSONObject.parseObject(send);
        if (null != jsonObject.getInteger("code") &&
            0 == jsonObject.getInteger("code")) {
            list.forEach(orderRecord -> {
                //更改未下发中状态
                orderRecord.setLogisticsPushState(LogisticsPushStateEnum.LOGISTICS_PUSH_20.getCode());
                orderService.updateOrderLogisState(orderRecord);
            });

        } else {
            log.info("返回信息格式不正确，不予更新订单信息");
        }
        log.info("erp 返回信息：data:{}",send);

        if (currentPage<15) {
            currentPage++;
            queryList(pageSize,currentPage);
        } else {
            return;
        }
    }

    /**
     * 调用erp
     * @param dataStr
     * @return
     */
    public String send(String dataStr){
        String response ="";
        WdtClient client = new WdtClient(Constants.wdtsid, Constants.wdtAppkey, Constants.wdtAppsecret, Constants.wdtTestUrl);
        Map<String, String> params = new HashMap<String, String>();
        params.put("shop_no", Constants.wdtAppkey);
        params.put("trade_list", dataStr);
        try {
            response = client.execute("trade_push.php", params);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return response;
    }

    /**
     * 数据组装
     * @param orderResp
     * @param trade_list
     * @param good
     * @param member
     */
    public void assembleOrderData(OrderResp orderResp,List<Map<String, Object>> trade_list,Map<String,String> good,Member member){
        String orderNo = orderResp.getOrderCode();
        List<Map<String, Object>> order_list = new ArrayList<Map<String, Object>>();
        Map<String, Object> order_1 = new HashMap<String, Object>();
        String time = DateUtil.format(new Date(), "YYYYMMDDHHmmss");
        String orderChild = orderNo + time;
        order_1.put("oid", orderChild);//订单编号
        order_1.put("num", orderResp.getCount());
        order_1.put("price", 0);
        order_1.put("status", 30);//trade_status=30	已付款待发货(包含货到付款)，30只可以直接变更为70/ 80这2种状态
        order_1.put("refund_status", 0);//退款状态,无退款
        order_1.put("goods_id", good.get("goods_id"));
        order_1.put("goods_name", good.get("goods_name"));
        order_1.put("spec_id", "");
        order_1.put("goods_no", "");//货品编码 平台货品SPU编码，对应ERP货品编号，尽量不为空
        order_1.put("spec_no", good.get("goods_Code"));//平台货品SKU唯一码，对应ERP商家编码，goods_no和spec_no不能同时为空
        order_1.put("discount", 0);		//子订单折扣
        order_1.put("adjust_amount", 0);	//手工调整,特别注意:正的表示加价,负的表示减价
        order_1.put("share_discount", 0);//分摊优惠


        order_list.add(order_1);
//        String time = DateUtil.format(new Date(), "YYYYMMDDHHmmss");
//        String orderChild = orderNo + time;
        Map<String, Object> trade_1 = new HashMap<String, Object>();
        trade_1.put("tid", orderNo);//订单id?
        trade_1.put("trade_status", 30);//已付款待发货(包含货到付款)，30只可以直接变更为70/ 80这2种状态
        trade_1.put("pay_status", "2");//,2:已付款
        trade_1.put("delivery_term", 1);//1:款到发货
        String tradeTime = DateUtil.format(new Date(), "yyyy-MM-dd HH:mm:ss");
        trade_1.put("trade_time", tradeTime);//下单时间
        trade_1.put("buyer_nick", member.getNickName());
        trade_1.put("receiver_name", member.getNickName());//收件人
        trade_1.put("receiver_mobile", member.getMobile());//收件人电话
        //trade_1.put("receiver_province", member.getProvince());
        //trade_1.put("receiver_city", member.getCity());
       // trade_1.put("receiver_district", member.getDistrictId());
        trade_1.put("receiver_address", member.getAddress());
//        trade_1.put("logistics_type", 4);
        trade_1.put("post_amount", 0);//邮费
        trade_1.put("cod_amount", 0);//货到付款金额
        trade_1.put("ext_cod_fee", 0);//货到付款买家费用
        trade_1.put("other_amount", 0);//其它收费
        trade_1.put("paid", 0);//已付款金额 paid = price * num
        trade_1.put("order_list", order_list);

        trade_list.add(trade_1);

    }


    public List<OrderResp> getOrderList(Integer pageSize, Integer currentPage){
        OrderQueryReq req = new OrderQueryReq();
        req.setCurrentPage(currentPage);
        req.setPageSize(pageSize);
        req.setWxDeliverType("1");
        req.setOrderType(String.valueOf(OrderTypeEnum.ORDER_TYPE_20.getCode()));
        req.setLogisticsPushState(LogisticsPushStateEnum.LOGISTICS_PUSH_10.getCode());
        JsonResult page = wxOrderResource.page(req);
        if (page.getState() != 0) {
            log.info("查询订单失败 跳出......................");
        }
        JSONObject data = (JSONObject) JSON.toJSON(page.getData());
        String content = data.getString("content");

        List<OrderResp> orderResps = JSONArray.parseArray(content, OrderResp.class);
        return orderResps;
    }



    /**
     *
     */
    //每五分钟执行一次
    @Scheduled(cron = "0 0/5 * * * ?")
    @PostMapping("/orderPushLogisticsWriteBackTask")
    public void orderPushLogisticsWriteBackTask(){
        //调用物流查询同步
        List<TradeVM> tradeVMS = this.LogisticsSyncQuery();
        if (CollectionUtils.isEmpty(tradeVMS)) {
            log.info("未查询到需要同步的物流信息，跳出");
            return;
        }
        Map<String,String> errorMap = new HashMap<>();
        Map<String,TradeVM> objMap = new HashMap<>();
        for (TradeVM tradeVM : tradeVMS) {

            try {
                //查询订单状态是否符合更新要求
                OrderRecord orderRecord =  orderService.queryOrderDetails(tradeVM.getTid());
                if (null == orderRecord) {
                    errorMap.put(tradeVM.getRec_id(),"同步失败 未查询到订单");
                    objMap.put(tradeVM.getRec_id(),tradeVM);
                    continue;
                }
                Integer state = orderRecord.getState();
                //订单状态为0时 更改订单信息
                if (0 == state) {

                    orderRecord.setState(1);
                    orderRecord.setLogisticsCodeErp(tradeVM.getLogistics_no());
                    orderRecord.setLogisticsName(tradeVM.getLogistics_name());
                    orderRecord.setLogisticsPushState(LogisticsPushStateEnum.LOGISTICS_PUSH_30.getCode());
                    orderService.updateOrderDetails(orderRecord);
                    ErpLogistics erpLogistics = new ErpLogistics();

                    BeanUtils.copyProperties(tradeVM, erpLogistics);

                    //新增rep 回调信息
                    erpLogisticsService.saveOne(erpLogistics);

                } else {
                    errorMap.put(tradeVM.getRec_id(),"同步失败 订单状态已发货");
                    objMap.put(tradeVM.getRec_id(),tradeVM);
                    log.info("错误，订单状态不为兑换成功，不更新订单状态与信息");
                }
            } catch (Exception e) {
                errorMap.put(tradeVM.getRec_id(),"同步失败 未知异常");
                objMap.put(tradeVM.getRec_id(),tradeVM);
                log.error("处理物流信息回写出现异常：data: {}",JSON.toJSONString(tradeVM));
                log.error("异常信息：",e);
            }

        }
        //调用物流回写
        this.LogisticsSyncAck(tradeVMS,errorMap,objMap);
    }

    /**
     *  物流信息查询与同步
     * @param
     */
    public List<TradeVM> LogisticsSyncQuery() {
        WdtClient client = new WdtClient(Constants.wdtsid, Constants.wdtAppkey, Constants.wdtAppsecret, Constants.wdtTestUrl);
        Map<String, String> params = new HashMap<String, String>();
        params.put("shop_no", Constants.wdtAppkey);
        params.put("is_part_sync_able", "0");
        params.put("limit", "100");
        try {
            String response = client.execute("logistics_sync_query.php", params);
            System.out.println(response);
            JSONObject jsonObject = JSON.parseObject(response);
            String message = jsonObject.getString("trades");
            //2、使用JSONArray
            List<TradeVM> list = JSONObject.parseArray(message, TradeVM.class);
            if(list !=null && list.size() >0){
                //物流同步回写
                return list;
            }
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 物流信息同步
     * @param list
     */
    public  JsonResult LogisticsSyncAck(List<TradeVM> list , Map<String,String> maps, Map<String,TradeVM> objMap){
        JsonResult result =new JsonResult();
        WdtClient client = new WdtClient(Constants.wdtsid, Constants.wdtAppkey, Constants.wdtAppsecret, Constants.wdtLogisticsSyncAckBaseUrl);
        List<Map<String, Object>> logistics_list = new ArrayList<Map<String, Object>>();
        Map<String, Object> logistics_1 =null;
        ErpLogistics  erplogistics =null;
        List<ErpLogistics> erpLogisticsList = new ArrayList<>();
        if(list !=null && list.size() >0){
            for (TradeVM vm:list) {
                logistics_1 = new HashMap<String, Object>();
                logistics_1.put("rec_id", vm.getRec_id());

                //
                if (maps.containsKey(vm.getRec_id())) {
                    logistics_1.put("status", 1);
                    logistics_1.put("message", maps.get(vm.getRec_id()));
                } else {
                    logistics_1.put("status", 0);
                    logistics_1.put("message", "同步成功");
                }
                logistics_list.add(logistics_1);
            }
        }

        String logistics_list_json = JSON.toJSONString(logistics_list);
        Map<String, String> params = new HashMap<String, String>();
        params.put("logistics_list", logistics_list_json);
        try {
            String response = client.execute("logistics_sync_ack.php", params);
            log.info("获取物流同步回写信息：{}",response);
            JSONObject jsonObject = JSON.parseObject(response);
            if (CollectionUtils.isEmpty(jsonObject.getJSONArray("errors"))&&
                "0".equals(jsonObject.getString("code"))) {
                log.info("物流同步回写发送成功");
            } else {
                log.info("数据异常 开始解析 物流同步回写信息");
                JSONArray errors = jsonObject.getJSONArray("errors");

                List<JSONObject> jsonObjects = errors.toJavaList(JSONObject.class);
                //处理失败数据
                for (JSONObject object : jsonObjects) {
                    object.getString("rec_id");

                    TradeVM ob = objMap.get(object.getString("rec_id"));
                    if (null == ob) {
                        log.info("未知返回数据");
                        continue;
                    }
                   //更新order 表数据
                    OrderRecord orderRecord =  orderService.queryOrderDetails(ob.getTid());
                    orderRecord.setLogisticsCodeErp(" ");
                    orderRecord.setLogisticsName(" ");
                    orderRecord.setState(0);
                  //  orderService.updateOrderDetails(orderRecord);
                }
            }
            result.setMessage(jsonObject.getString("message"));
            result.setState(jsonObject.getInteger("code"));
            return result;
        } catch (IOException e) {
            e.printStackTrace();
            result.setMessage(e.getMessage());
            result.setState(500);
            return result;
        }
    }

}
